/*******************************************************************/
/*    Copyright (c) 1999-2020 by Spatial Corp.                     */
/*    All rights reserved.                                         */
/*    Protected by U.S. Patents 5,257,205; 5,351,196; 6,369,815;   */
/*                              5,982,378; 6,462,738; 6,941,251    */
/*    Protected by European Patents 0503642; 69220263.3            */
/*    Protected by Hong Kong Patent 1008101A                       */
/*******************************************************************/

//----------------------------- IopAcisPartExport.cpp -------------------------------

#include <iostream>
#include <fstream>
#include <vector>
#include <time.h>
#include <cmath> // fabs

//Acis
#include "lists.hxx"
#include "kernapi.hxx" 

//Iop
#include "SPAIop.h"
#include "SPAIopAcis.h"
#include "SPAIopMisc.h"
#include "SPAIopVisu.h"
#include "SPAIopPolicyOptions.h"
#include "SPAIopArgParser.h"
#include "SPAIopSampleUtilities.h"
#include "SPAIopAcisSampleUtilities.h"
#include "SPAIopSampleResultUtils.h"
#include "SPAIopVisualization.h"
#include "SPAIopPMIData.h"
#include "SPAIopMappingData.h"
#include "SPAIopFeatureUtils.h"
#include "SPAIopAcisFeatureUtils.h"
#include "SPAIopDocumentDataImporter.h"
#include "SPAIopDocumentDataImportResult.h"

#define CurrentReferenceType SPAIopOutputPSReference
#include "SPAIopVisualizationTransfer.h"
#undef CurrentReferenceType 
#include "SPAIopPerformanceStatistics.h"
// License file
#include "spatial_license.h"
using namespace SPAIopSampleLogging;
using namespace SPAIopAcisPrintUtils;
using namespace SPAIopAcisPSVisualizationUtils;
using namespace SPAIopFeatureUtils;
using namespace SPAIopAcisFeatureUtils;

//-----------------------------------------------------------------------------------------


int ImportAndExportModel(const wchar_t*& ipSourceFilePath, const wchar_t*& ipTargetFilePath, const SPAIopPolicy& iPolicy);
bool ImportProductStructure(SPAIopDocument& iSourceDoc, SPAIopInputProductStructure &oInputPS, const SPAIopPolicy& iPolicy, SPAIopPSImportResult &oInputPSResult);
bool IsInputPartFile(const SPAIopInputProductStructure& iInputPS);
void ImportPartVisu(SPAIopPartDocument& iAcisInteropPartDocument, const SPAIopPolicy& iPolicy, SPAIopVisuData& oVisuData);
int ImportPSReference(SPAIopInputPSReference& iInputReference, SPAIopInputPSMissingFileIter& iMissingFiles, const SPAIopPolicy& iPolicy, int& opNumDefined, const std::vector< std::wstring >& iInstLongPIdList, SPAtransf& iInstanceTransform,
	const SPAIopWString& iConfigName, ENTITY_LIST& oFlattenEntList, SPAIopInputPSInstance& iInputInstance, std::vector< std::map <std::wstring, ENTITY_LIST>>& iVectorOfStringToEntitiesMap);

//-----------------------------------------------------------------------------------------

class ProgressReporter;

static bool _g_doingVisualization = false;
static bool _g_translateVisualization = false;
static bool _g_translateBrep = true;
static bool _g_transferMiscData = false;
static bool _isToUseInputVisualization = false;



//-----------------------------------------------------------------------------------------

void PrintHelp()
{
	PrintMessage(L"Usage: IopAcisPartExport -i <full-input-file-path> -o <full-output-file-path> [-p <full-policy-file-path>] [-log <full-log-file-path>] [-viz 0/1] [-brep 1/0] [-misc <data-transfer-mode>] [-useInputVisu 0/1] [-h] \n");
	PrintMessage(L"\t-i	: The absolute path to the input file. \n");
	PrintMessage(L"\t-o	: The absolute path to the output file. \n");
	PrintMessage(L"\t-p	: The absolute path to the policy file used to control optional behavior during operations. \n");
	PrintMessage(L"\t-log	: The absolute path to the log file. \n");
	PrintMessage(L"\t-brep	: False or 0 supresses translation of BRep. \n");
	PrintMessage(L"\t\t  Default is to translate BRep. \n");
	PrintMessage(L"\t-viz	: True or 1 translates Visualization. \n");
	PrintMessage(L"\t-useInputVisu   : Set input visualization on output reference(0/1). Choose to set input visualization on output or not .\n				0=Set new output visualization data created from input visualization on output reference(default).\n				1=Set input visualization data on output reference.\n");
	PrintMessage(L"\t-misc	: 1 to transfer the MiscData data, (0 default). \n");
	PrintMessage(L"\t\t  misc data option is only applicable when brep is 1 and viz is 0. \n");
	PrintMessage(L"\t-h	: This help.\n");
}

//-----------------------------------------------------------------------------------------



bool IsInputPartFile(const SPAIopInputProductStructure& iInputPS)
{
	// Some code to check if input fle is single part file.
	int refCount = iInputPS.GetUniqueReferencesCount();
	if (refCount != 1)
		return false;

	SPAIopInputPSReference inputPSRef = iInputPS.GetUniqueReference(0);
	int instCount = iInputPS.GetRootInstancesCount();
	if (1 != instCount)
		return false;

	SPAIopInputPSInstance inputPartInstance = iInputPS.GetRootInstance(0);

	double affineTransform[3][3] = { { 1.0, 0.0, 0.0 },{ 0.0, 1.0, 0.0 },{ 0.0, 0.0, 1.0 } };
	double translation[3] = { 0. };
	inputPartInstance.GetInstancePositionMatrix(affineTransform, translation);
	bool isIdentity = true;
	for (int i = 0; i<3; i++)
	{
		for (int j = 0; j<3; j++)
		{
			double val = affineTransform[i][j];
			if (isIdentity)
			{
				if (i == j && (std::fabs(val - 1.0) > 1e-10))
					isIdentity = false;
				else if (i != j && std::fabs(val) > 1e-10)
					isIdentity = false;
			}
			else
				break;
		}
		if (std::fabs(translation[i]) > 1e-10)
			isIdentity = false;
	}

	if (!isIdentity)
		return false;

	SPAIopInputPSReference inputPartPSRef = inputPartInstance.GetReference();
	if (!inputPartPSRef.IsPart())
		return false;

	return true;
}

//-----------------------------------------------------------------------------------------

int ImportAndExportModel(const wchar_t*& ipSourceFilePath, const wchar_t*& ipTargetFilePath, const SPAIopPolicy& iPolicy)
{
	int returnValue = SPAIopSampleResult_Import_Ok;

	_g_pProgressReporter = new ProgressReporter();

	// Import Input Product Structure 
	SPAIopInputProductStructure inputPS;
	SPAIopPSImportResult inputPSResult;
	SPAIopWString wSourceFilePath(ipSourceFilePath);
	SPAIopDocument sourceDoc(wSourceFilePath);
	bool gotPS = ImportProductStructure(sourceDoc, inputPS, iPolicy, inputPSResult);

	if (!gotPS)
	{
		// If the product structure can't be loaded there's no way to translate anything
		return SPAIopSampleResult_Import_PS_Fail;
	}
	SPAIopAcisOutputPart outputPart;
	bool inputIsPartFile = IsInputPartFile(inputPS);
	SPAIopDocumentDataImporter psDataImporter;
	SPAIopDocumentDataImportResult psRootDataResult = psDataImporter.ImportWithPolicy(iPolicy, sourceDoc);
	if (true == inputIsPartFile)
	{
		SPAIopEntityIter entityIter = psRootDataResult.GetOccurrenceEntityIterator();
		int count = entityIter.GetCount();
		if (count > 0)
			inputIsPartFile = false; // real assembly
	}
	if (true == inputIsPartFile)
	{
		SPAIopInputPSInstance inputPartInstance = inputPS.GetRootInstance(0);
		SPAIopInputPSReference inputPartRef = inputPartInstance.GetReference();
		SPAIopPartDocument partReferneceDoc = inputPartRef.GetDocument();

		if (_g_translateVisualization)
		{
			SPAIopVisuData iopPartVisuData;
			ImportPartVisu(partReferneceDoc, iPolicy, iopPartVisuData);
			if (!_isToUseInputVisualization)
			{
				SPAIopVisuOutputData vizOutData;
				int res = SPAIopVisualizationTransfer::TransferVisualizationData(iopPartVisuData, vizOutData);
				outputPart.SetVisualizationOutputData(vizOutData);
			}
			else
			{
				outputPart.SetVisualizationData(iopPartVisuData);
			}
		}

		if (_g_translateBrep)
		{
			if (nullptr != _g_pProgressReporter)
			{
				_g_pProgressReporter->SetNumParts(inputPS.GetUniqueReferencesCount());
				size_t numNonMissingParts = GetNonMissingParts(inputPS, inputPSResult);
				_g_pProgressReporter->setNonMissingParts(numNonMissingParts);
				_g_pProgressReporter->SetPsDone(true);
			}

			ENTITY_LIST* iopAcisEntities = ACIS_NEW ENTITY_LIST;
			SPAIopPartImportResult partImportResult;
			SPAIopAcisPartImporter partImporter;
			partImportResult = partImporter.ImportWithPolicy(iPolicy, partReferneceDoc, *iopAcisEntities);

			if (iopAcisEntities && iopAcisEntities->count() > 0)
			{
				outputPart.SetPartEntities(*iopAcisEntities);

				if (_g_transferMiscData)
				{
					TransferPartReferenceMiscData(inputPartRef, partImportResult, outputPart);
				}

				if (_g_translateVisualization)
				{
					SPAIopPMIData pmiData = partImportResult.GetPMIData();
					outputPart.SetPMIData(pmiData);
					SPAIopMappingData mappingData = partImportResult.GetMappingData();
					outputPart.SetMappingData(mappingData);
				}
			}
		}

		
	}
	else   
	{
		
		ProcessAssemblyFeatureData(psRootDataResult, iPolicy);
		if (NULL != _g_pProgressReporter)
		{
			_g_pProgressReporter->SetNumParts(inputPS.GetUniqueReferencesCount());
			size_t numNonMissingParts = GetNonMissingParts(inputPS, inputPSResult);
			_g_pProgressReporter->setNonMissingParts(numNonMissingParts);
			_g_pProgressReporter->SetPsDone(true);
		}
		bool success = true;
		int result = SPAIopSampleResult_Import_Ok;
		SPAIopInputPSMissingFileIter missingFiles = inputPSResult.GetMissingFileIterator();
		SPAIopWString productName = inputPS.GetProductName();
		SPAIopWString productPID;
		bool hasPID = inputPS.GetPID(productPID);
		if (hasPID)
		{
			const wchar_t* prodName = NULL;
			productPID.ToWChar(prodName);
		}

		ENTITY_LIST flattenEntList;

		int nbInstances = inputPS.GetRootInstancesCount();
		const wchar_t* wProductName = NULL;
		productName.ToWChar(wProductName);
		std::wstring nodeProductName = std::wstring(wProductName);
		int copiedInstances = 0;
		std::vector< std::map <std::wstring, ENTITY_LIST>> vectorOfRootStringToEntitiesMap;
		SPAtransf rootTransform;
		for (int i = 0; i < nbInstances && true == success; i++)
		{
			SPAIopInputPSInstance inputRootInstance = inputPS.GetRootInstance(i);
			SPAIopWString iConfigName;
			SPAIopPSInstanceMiscData miscData = inputRootInstance.GetMiscData();
			iConfigName = miscData.GetConfigurationName();
			bool skipInstance = ShouldInstanceSkipped(inputRootInstance);
			if (true == skipInstance)
			{
				continue;
			}
			SPAtransf instanceTransform;
			SPAIopInputPSReference inputReference = inputRootInstance.GetReference();
			SPAIopWString referenceStorageName = inputReference.GetStorageName();
			bool isMissingReference = missingFiles.ContainsPath(referenceStorageName);

			std::vector< std::wstring > emptyInstLongPIdList;
			emptyInstLongPIdList.push_back(nodeProductName);
			std::vector< std::wstring > instLongPIdList;
			GetAcisTransformAndInstPIdStringArray(inputRootInstance, instanceTransform, emptyInstLongPIdList, instLongPIdList);
			std::vector< std::map <std::wstring, ENTITY_LIST>> vectorOfStringToEntitiesMap;
			std::map <std::wstring, ENTITY_LIST> currentInstStringToEntitiesMap;
			vectorOfStringToEntitiesMap.push_back(currentInstStringToEntitiesMap);

			if (false == isMissingReference)
			{
				unsigned int refID = inputReference.GetUniqueID();

				int numDefined = 0;
				int res = ImportPSReference(inputReference, missingFiles, iPolicy, numDefined, instLongPIdList, instanceTransform, iConfigName, flattenEntList, inputRootInstance, vectorOfStringToEntitiesMap);
				if (0 != res)
					result = res;
				if (numDefined > 0)
				{
					copiedInstances += numDefined;
				}
			}
			int t = (int)vectorOfStringToEntitiesMap.size();
			std::map <std::wstring, ENTITY_LIST> currentInstStringToEntitiesMap1 = vectorOfStringToEntitiesMap[t - 1];
			vectorOfRootStringToEntitiesMap.push_back(currentInstStringToEntitiesMap1);
			vectorOfStringToEntitiesMap.erase(vectorOfStringToEntitiesMap.end() - 1);
		}

		int size = (int)vectorOfRootStringToEntitiesMap.size();
		for (int k = 0; k < size; k++)
		{
			LinkAndPerformAssemCutOnCurrentAssemOnAcisEnt(rootTransform, vectorOfRootStringToEntitiesMap[k]);
			FlattenRootAssemAcis(vectorOfRootStringToEntitiesMap[k], flattenEntList);
		}
		outputPart.SetPartEntities(flattenEntList);
	}
	SPAIopWString wTargetFilePath(ipTargetFilePath);

	{
		SPAIopPartExporter exporter;
		try
		{
			if (nullptr != _g_pProgressReporter)
				_g_pProgressReporter->SetExportStarts(true);

			exporter.SetProgressCallBack((SPAIopProgressCallback)MyProgressCallBack);
			SPAIopResult res = exporter.ExportWithPolicy(iPolicy, outputPart, wTargetFilePath);
		}
		catch (const SPAIopAcisError& error)
		{
			DisplayError(error);
			returnValue = 1;
		}
		catch (...)
		{
			returnValue = SPAIopSampleResult_Export_PS_Fail;
			std::wcout << "FAILURE: Unknown exception caught! " << std::endl;
		}
	}
	delete _g_pProgressReporter;
	_g_pProgressReporter = NULL;
	return returnValue;
}

int ImportPSReference(SPAIopInputPSReference& iInputReference, SPAIopInputPSMissingFileIter& iMissingFiles, const SPAIopPolicy& iPolicy, int& opNumDefined, const std::vector< std::wstring >& iInstLongPIdList, SPAtransf& iInstanceTransform,
	const SPAIopWString& iConfigName, ENTITY_LIST& oFlattenEntList, SPAIopInputPSInstance& iInputInstance, std::vector< std::map <std::wstring, ENTITY_LIST>>& iVectorOfStringToEntitiesMap)
{
	SPAIopPartDocument partReferneceDoc = iInputReference.GetDocument();
	int numDefined = 0;
	int result = SPAIopSampleResult_Import_Ok;
	bool isAlreadyDefine = UserAlreadyImported(iInputReference, iConfigName);
	if (iInputReference.IsPart())    // part node
	{
		unsigned int currentID = iInputReference.GetUniqueID();
		if (!isAlreadyDefine)
		{
			// import the document
			SPAIopPartImportResult partImportResult;
			SPAIopAcisPartImporter partImporter;
			ENTITY_LIST* iopAcisEntities = ACIS_NEW ENTITY_LIST;
			partImportResult = partImporter.ImportWithPolicy(iPolicy, partReferneceDoc, *iopAcisEntities);

			bool addedDataToPartRef = false;
			ENTITY_LIST copiedEntityList;  
			if (iopAcisEntities && iopAcisEntities->count() > 0)
			{
				bool applyTransOnCopiedEnt = false;
				CopyAcisEntityAndApplyTransform(*iopAcisEntities, iInstanceTransform, copiedEntityList, applyTransOnCopiedEnt);
			}

			_uniqueIdToEntitiesMap[currentID] = copiedEntityList;

			bool isTarget = false;
			bool isLinkedToCutFeature = IsInstanceLinkedToCutFeature(iInstLongPIdList, isTarget);
			ENTITY* pNodeEnt = NULL;
			if (iopAcisEntities && iopAcisEntities->count() > 0)
			{
				iopAcisEntities->init();
				while (pNodeEnt = iopAcisEntities->next())
				{
					SetAttributesOnAcisEnt(iInputInstance, pNodeEnt);
					if (false == isLinkedToCutFeature)                            
						oFlattenEntList.add(pNodeEnt, TRUE);
				}
			}
			int longPIdNum = (int)iVectorOfStringToEntitiesMap.size();
			if (true == isTarget)
			{
				for (int i = 0; i < longPIdNum; i++)
				{
					std::wstring longPId = iInstLongPIdList[i];
					iVectorOfStringToEntitiesMap[i][longPId] = *iopAcisEntities;
				}
			}

			if (true == addedDataToPartRef)
			{
				numDefined += 1;
			}
		}
		else
		{
			ENTITY_LIST partEntList;
			ENTITY_LIST copiedEntityList;
			auto search = _uniqueIdToEntitiesMap.find(currentID);

			if (_uniqueIdToEntitiesMap.end() != search)
			{
				partEntList = search->second;
			}
			bool applyTransOnCopiedEnt = true;
			CopyAcisEntityAndApplyTransform(partEntList, iInstanceTransform, copiedEntityList, applyTransOnCopiedEnt);
			bool isTarget = false;
			bool isLinkedToCutFeature = IsInstanceLinkedToCutFeature(iInstLongPIdList, isTarget);

			ENTITY* pNodeEnt = NULL;
			copiedEntityList.init();
			while (pNodeEnt = copiedEntityList.next())
			{
				SetAttributesOnAcisEnt(iInputInstance, pNodeEnt);
				if (false == isLinkedToCutFeature)
					oFlattenEntList.add(pNodeEnt, TRUE);
			}
			int longPIdNum = (int)iVectorOfStringToEntitiesMap.size();
			if (true == isTarget)
			{
				for (int i = 0; i < longPIdNum; i++)
				{
					std::wstring longPId = iInstLongPIdList[i];
					iVectorOfStringToEntitiesMap[i][longPId] = copiedEntityList;
				}
			}
			numDefined = 1;
		}
	}
	else   // sub-assembly node
	{
		if (false == isAlreadyDefine)
		{
			SPAIopDocumentDataImporter psDataImporter;
			SPAIopDocumentDataImportResult psNodeRefDataResult = psDataImporter.ImportWithPolicy(iPolicy, iInputReference);
			ProcessAssemblyFeatureData(psNodeRefDataResult, iPolicy);
		}
		int nbInstances = iInputReference.GetInstancesCount();
		if (nbInstances > 0)
		{
			std::vector< std::map <std::wstring, ENTITY_LIST>> vectorRootStringToEntitiesMap;
			std::map <std::wstring, ENTITY_LIST> dummyMap;
			for (int i = 0; i < nbInstances; i++)
			{

				SPAIopInputPSInstance iNodeInstance = iInputReference.GetInstance(i);
				SPAIopWString iNodeConfigName;
				SPAIopPSInstanceMiscData miscData = iNodeInstance.GetMiscData();
				iNodeConfigName = miscData.GetConfigurationName();
				bool skipInstance = ShouldInstanceSkipped(iNodeInstance);
				if (true == skipInstance)
				{
					continue;
				}
				SPAtransf nodeInstanceTransform;
				SPAIopInputPSReference iNodeReference = iNodeInstance.GetReference();
				SPAIopWString referenceStorageName = iNodeReference.GetStorageName();
				bool isMissingReference = iMissingFiles.ContainsPath(referenceStorageName);

				std::vector< std::wstring > nodeLongPIdList;
				GetAcisTransformAndInstPIdStringArray(iNodeInstance, nodeInstanceTransform, iInstLongPIdList, nodeLongPIdList);
				std::map <std::wstring, ENTITY_LIST> currentInstStringToEntitiesMap;
				iVectorOfStringToEntitiesMap.push_back(currentInstStringToEntitiesMap);

				nodeInstanceTransform = nodeInstanceTransform * iInstanceTransform;
				if (false == isMissingReference)
				{
					unsigned int refID = iNodeReference.GetUniqueID();

					int entities = 0;
					int res = ImportPSReference(iNodeReference, iMissingFiles, iPolicy, entities, nodeLongPIdList, nodeInstanceTransform, iNodeConfigName, oFlattenEntList, iNodeInstance, iVectorOfStringToEntitiesMap);// Recursively navigate nodes below this sub-assembly node
					if (0 != res)
						result = res;
					if (entities > 0)
					{
						numDefined += entities;
					}
				}
				int t = (int)iVectorOfStringToEntitiesMap.size();
				std::map <std::wstring, ENTITY_LIST> currentInstStringToEntitiesMap1 = iVectorOfStringToEntitiesMap[t - 1];
				vectorRootStringToEntitiesMap.push_back(currentInstStringToEntitiesMap1);
				iVectorOfStringToEntitiesMap.erase(iVectorOfStringToEntitiesMap.end() - 1);
			}
			int size = (int)vectorRootStringToEntitiesMap.size();
			for (int k = 0; k < size; k++)
			{
				LinkAndPerformAssemCutOnCurrentAssemOnAcisEnt(iInstanceTransform, vectorRootStringToEntitiesMap[k]);
			}
		}
	}
	opNumDefined = numDefined;
	return result;
}

//-----------------------------------------------------------------------------------------

bool ImportProductStructure(SPAIopDocument& iSourceDoc, SPAIopInputProductStructure& oInputPS, const SPAIopPolicy& iPolicy, SPAIopPSImportResult &oInputPSResult)
{
	bool returnValue = true;
	// Import the Assembly tree as a Product Structure.  Note that 
	// importing a Product Structure does not import any brep data associated
	// with the model, which is done separately from part-associated reference nodes
	// in the Product Structure.  Use try/catch exception handling blocks to 
	// manage fatal errors.

	// Create Source Document from input file	 
	

	// Create a Product Strcuture Importer
	SPAIopProductStructureImporter psImporter;
	try
	{
		// Set Interop global progress report function if not already done
		psImporter.SetProgressCallBack((SPAIopProgressCallback)MyProgressCallBack);

		oInputPSResult = psImporter.ImportWithPolicy(iPolicy, iSourceDoc, oInputPS);

	}
	catch (const SPAIopAcisError& error)
	{
		DisplayError(error);
		returnValue = false;
	}
	catch (...)
	{
		std::wcout << "FAILURE: Unknown exception caught! " << std::endl;
		returnValue = false;
	}

	return returnValue;
}


//-----------------------------------------------------------------------------------------

void ImportPartVisu(SPAIopPartDocument& iAcisInteropPartDocument, const SPAIopPolicy& iPolicy, SPAIopVisuData& oVisuData)
{
	// Import the visualization data of a part into the given SPAIopVisuData using the Import 
	// method of a SPAIopVisualizationImporter object.  Use try/catch exception handling blocks to 
	// manage fatal errors.

	SPAIopVisualizationImporter visuImporter;
	try
	{
		SPAIopVisuImportResult importRes = visuImporter.ImportWithPolicy(iPolicy, iAcisInteropPartDocument);

		oVisuData = importRes.GetVisualizationData();
	}
	catch (const SPAIopAcisError& error)
	{
		DisplayError(error);
	}
	catch (...)
	{
		std::wcout << "FAILURE: Unknown exception caught! " << std::endl;
	}
}

//-----------------------------------------------------------------------------------------
const char* GetUConnectLicenseKey();

int test_IopAcisPartExport(int argc, char* argv[])
{
	// This sample uses a guard class that initializes InterOp upon 
	// construction and terminates InterOp upon destruction.  All 
	// translations are done within the boundaries of a single 
	// initialization and shutdown.  InterOp may only be initialized 
	// and shutdown once per process.  Please do not use the guard 
	// classes multiple times per process.
	int result = 1;
	SPAIopPerformanceStatistics printPerfoStatsObj;

	api_start_modeller(0);

	try
	{
		

		char* argFields[] = { "i", "o", "p", "v", "h", "brep", "viz", "useInputVisu", "misc", "log" };
		int size = sizeof(argFields) / sizeof(*argFields);
		SPAIopArgParser parser(size, argFields, argc, argv, &PrintHelp);

		SPAIopAcisSystemInitGuard initGuard(SPATIAL_LICENSE);

		result = initGuard.GetInitStatus();

		if (true == parser.IsSuccess())
		{

			const wchar_t* pSourceFilePath = NULL;
			bool hasInputFileName = parser.GetWStringValueFor("i", pSourceFilePath); // GetStringValueFor


			const wchar_t* pTargetFilePath = NULL;
			bool hasOutputFileName = parser.GetWStringValueFor("o", pTargetFilePath);


			const wchar_t* pPolicyFilePath = NULL;
			bool hasPolicyFileName = parser.GetWStringValueFor("p", pPolicyFilePath);

			const wchar_t* pLogFilePath = NULL;
			bool hasLogFileName = parser.GetWStringValueFor("log", pLogFilePath);

			int visuFlag = 0;
			bool hasVisuFlag = parser.GetIntegerValueFor("v", visuFlag);

			if (hasVisuFlag && (visuFlag != 0))
			{
				_g_doingVisualization = true;
			}

			int translateVisuFlag = 0;
			bool translateVisu = parser.GetIntegerValueFor("viz", translateVisuFlag);

			if (translateVisu && 0 != translateVisuFlag)
			{
				_g_translateVisualization = true;
			}

			int translateBrepFlag = 0;
			bool translateBRep = parser.GetIntegerValueFor("brep", translateBrepFlag);

			if (translateBRep && 0 == translateBrepFlag)
			{
				_g_translateBrep = false;
			}

			int miscFlag = 0;
			bool miscDataFlag = parser.GetIntegerValueFor("misc", miscFlag);

			if (miscDataFlag && (miscFlag != 0))
			{
				_g_transferMiscData = true;
			}

			int inputVisuFlag = 0;
			bool hasInputVisuFlag = parser.GetIntegerValueFor("useInputVisu", inputVisuFlag);

			if (hasInputVisuFlag && (inputVisuFlag != 0))
			{
				_isToUseInputVisualization = true;
			}

			bool isTranslationValid = _g_translateBrep || _g_translateVisualization;

			if (hasInputFileName && hasOutputFileName && pSourceFilePath && pTargetFilePath)
			{
				SPAIopPolicy policy;
				if (0 != pPolicyFilePath)
				{
					SPAIopWString policyFilePath(pPolicyFilePath);
					SPAIopPolicyFileStreamXML xmlPolicyStream;
					xmlPolicyStream.SetUnstreamFilePath(policyFilePath);

					policy.Deserialize(xmlPolicyStream);
				}

				SetOrUpdateLogFileInPolicy(pLogFilePath, policy);

				if (isTranslationValid)
					result = ImportAndExportModel(pSourceFilePath, pTargetFilePath, policy);
				else
				{
					std::wcout << "\nFAILURE: Option value can't  be \"-brep 0 and -viz 0\"";
					result = 1;
				}
				DeleteMappedAcisEntity();
			}
			else
			{
				PrintHelp();
			}
		}
	}
	catch (const SPAIopAcisError& fatalErr)
	{
		DisplayError(fatalErr);
		result = 1;
	}
	catch (...)
	{
		PrintMessage(L"FAILURE: Unknown exception caught! ");
		result = 1;
	}

	api_stop_modeller();

	return result;
}

//-----------------------------------------------------------------------------------------
